package com.genexususa.eo.google.connection;

import com.genexususa.eo.google.data.*;
import com.google.api.ads.adwords.axis.v201406.cm.*;
import com.google.api.ads.adwords.axis.v201406.cm.DateRange;
import com.google.api.ads.adwords.axis.v201406.cm.OrderBy;
import com.google.api.ads.adwords.axis.v201406.cm.Paging;
import com.google.api.ads.adwords.axis.v201406.cm.Predicate;
import com.google.api.ads.adwords.axis.v201406.cm.PredicateOperator;
import com.google.api.ads.adwords.axis.v201406.cm.ReportDefinitionReportType;
import com.google.api.ads.adwords.axis.v201406.cm.Selector;
import com.google.api.ads.adwords.axis.v201406.cm.SortOrder;
import com.google.api.ads.adwords.lib.client.AdWordsSession;
import com.google.api.ads.adwords.lib.jaxb.v201406.*;
import com.google.api.ads.adwords.lib.utils.ReportDownloadResponse;
import com.google.api.ads.adwords.lib.utils.ReportDownloadResponseException;
import com.google.api.ads.adwords.lib.utils.ReportException;
import com.google.api.ads.adwords.lib.utils.v201406.ReportDownloader;
import com.google.api.ads.common.lib.auth.OfflineCredentials;
import com.google.api.ads.common.lib.conf.ConfigurationLoadException;
import com.google.api.ads.common.lib.exception.OAuthException;
import com.google.api.ads.common.lib.exception.ValidationException;
import com.google.api.ads.common.lib.utils.Streams;
import com.google.api.client.auth.oauth2.Credential;
import com.google.common.collect.Lists;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.*;
import java.io.*;
import java.util.ArrayList;
import java.util.List;


public class AdGroupCriterionManager {


    private static final int PAGE_SIZE = 5000;
    private String _clientId;

    public void SetClientId(String clientId) {
        this._clientId = clientId;
    }

    public String GetClientId() {
        return _clientId;
    }

    public void Finalize() {

        SessionController sc = SessionController.getInstance();
        sc.RemoveSession(_clientId);
    }


    public String CreateAdGroupCriterion(String xml) {

        try {


            String result = "";

            // Get the instance of service's factory
            ServiceFactory sf = ServiceFactory.getInstance();

            // Get AdGroup Service
            AdGroupCriterionServiceInterface adGroupCriterionService = sf.GetAdGroupCriterionService(this.GetClientId());

            //GA_ResultCreateCriterion res = new GA_ResultCreateCriterion();
            GA_Result res = new GA_Result();

            //try{

            Util util = new Util();

            Document doc = util.loadXMLFromString(xml);

            XPathFactory factory = XPathFactory.newInstance();
            XPath xpath = factory.newXPath();

            XPathExpression expr = xpath.compile("//GA_Criterion");

            Object criterionNodes = expr.evaluate(doc, XPathConstants.NODESET);

            NodeList criterions = (NodeList) criterionNodes;

            ArrayList<GA_ResultItem> groupCriterions = new ArrayList<GA_ResultItem>();

            if (criterions.getLength() > 0) {

                for (int i = 0; i < criterions.getLength(); i++) { // For all GA_Criterion Nodes

                    Node n = criterions.item(i);

                    NodeList children = n.getChildNodes();

                    if (children.getLength() > 0) {

                        String criterionUse = "";

                        for (int j = 0; j < children.getLength(); j++) {

                            if (children.item(j).getNodeName().equalsIgnoreCase("CriterionUse")) {
                                criterionUse = children.item(j).getTextContent();
                                break;
                            }
                        }

                        //GA_Criterion criterion = new GA_Criterion();

                        GA_ResultItem criterion = new GA_ResultItem();

                        if (criterionUse.equalsIgnoreCase("B")) { // BiddableAdGroupCriterion

                            BiddableAdGroupCriterion biddableCriterion = new BiddableAdGroupCriterion();

                            for (int j = 0; j < children.getLength(); j++) {

                                if (children.item(j).getNodeName().equalsIgnoreCase("AdGroupId")) {

                                    biddableCriterion.setAdGroupId(Long.parseLong(children.item(j).getTextContent()));

                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("CampaignGxId")) {
                                    criterion.SubCampaignGxId = Long.parseLong(children.item(j).getTextContent());
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("AdGroupGxId")) {
                                    criterion.AdGroupGxId = Long.parseLong(children.item(j).getTextContent());
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("CriterionGxId")) {
                                    criterion.CriterionGxId = Long.parseLong(children.item(j).getTextContent());
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("CampaignID")) {
                                    criterion.CampaignId = Long.parseLong(children.item(j).getTextContent());
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("AdGroupId")) {
                                    criterion.AdGroupId = Long.parseLong(children.item(j).getTextContent());
                                }


                                if (children.item(j).getNodeName().equalsIgnoreCase("UserStatus")) {

                                    if (children.item(j).getTextContent().equalsIgnoreCase("A")) {
                                        biddableCriterion.setUserStatus(UserStatus.ENABLED);
                                    } else if (children.item(j).getTextContent().equalsIgnoreCase("D")) {
                                        biddableCriterion.setUserStatus(UserStatus.REMOVED);
                                    } else if (children.item(j).getTextContent().equalsIgnoreCase("P")) {
                                        biddableCriterion.setUserStatus(UserStatus.PAUSED);
                                    }
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("ServingStatus")) {

                                    if (children.item(j).getTextContent().equalsIgnoreCase("E")) {
                                        biddableCriterion.setSystemServingStatus(SystemServingStatus.ELIGIBLE);
                                    } else if (children.item(j).getTextContent().equalsIgnoreCase("RS")) {
                                        biddableCriterion.setSystemServingStatus(SystemServingStatus.RARELY_SERVED);
                                    }

                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("ApprovalStatus")) {

                                    if (children.item(j).getTextContent().equalsIgnoreCase("A")) {
                                        biddableCriterion.setApprovalStatus(ApprovalStatus.APPROVED);
                                    } else if (children.item(j).getTextContent().equalsIgnoreCase("PR")) {
                                        biddableCriterion.setApprovalStatus(ApprovalStatus.PENDING_REVIEW);
                                    } else if (children.item(j).getTextContent().equalsIgnoreCase("UR")) {
                                        biddableCriterion.setApprovalStatus(ApprovalStatus.UNDER_REVIEW);
                                    } else if (children.item(j).getTextContent().equalsIgnoreCase("D")) {
                                        biddableCriterion.setApprovalStatus(ApprovalStatus.DISAPPROVED);
                                    }
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("DisapprovalReasons")) {

                                    biddableCriterion.setDisapprovalReasons(new String[]{children.item(j).getTextContent()});
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("DestinationUrl")) {

                                    biddableCriterion.setDestinationUrl(children.item(j).getTextContent());
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("Keyword")) {
                                    biddableCriterion.setCriterion(GetKeywordCriterion(children.item(j).getChildNodes()));
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("Placement")) {
                                    biddableCriterion.setCriterion(GetPlacementCriterion(children.item(j).getChildNodes()));
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("Vertical")) {
                                    biddableCriterion.setCriterion(GetVerticalCriterion(children.item(j).getChildNodes()));
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("UserInterest")) {
                                    biddableCriterion.setCriterion(GetUserInterestCriterion(children.item(j).getChildNodes()));
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("Gender")) {
                                    biddableCriterion.setCriterion(GetGenderCriterion(children.item(j).getChildNodes()));
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("AgeRange")) {
                                    biddableCriterion.setCriterion(GetAgeRangeCriterion(children.item(j).getChildNodes()));
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("BiddingStrategyConfiguration")) {

                                    BiddingStrategyConfiguration bsc = new BiddingStrategyConfiguration();
                                    NodeList biddingStrategyConfiguration = children.item(j).getChildNodes();

                                    if (biddingStrategyConfiguration.getLength() > 0) {
                                        for (int a = 0; a < biddingStrategyConfiguration.getLength(); a++) {
                                            if (biddingStrategyConfiguration.item(a).getNodeName().equalsIgnoreCase("BiddingScheme")) {

                                                NodeList strategies = biddingStrategyConfiguration.item(a).getChildNodes();

                                                if (strategies.getLength() > 0) {

                                                    for (int y = 0; y < strategies.getLength(); y++) {

                                                        if (strategies.item(y).getNodeName().equalsIgnoreCase("BSConversionOptimizer")) {
                                                            Node bsConversionOptimizer = strategies.item(y);

                                                            NodeList bsConversionOptimizerChildren = bsConversionOptimizer.getChildNodes();

                                                            if (bsConversionOptimizerChildren.getLength() > 0) {

                                                                ConversionOptimizerBiddingScheme co = new ConversionOptimizerBiddingScheme();

                                                                for (int index = 0; index < bsConversionOptimizerChildren.getLength(); index++) {

                                                                    if (bsConversionOptimizerChildren.item(index).getNodeName().equalsIgnoreCase("BSConvOptPricingModel")) {
                                                                        if (bsConversionOptimizerChildren.item(index).getTextContent().equalsIgnoreCase("C")) {
                                                                            co.setPricingMode(ConversionOptimizerBiddingSchemePricingMode.CLICKS);
                                                                        } else if (bsConversionOptimizerChildren.item(index).getTextContent().equalsIgnoreCase("CN")) {
                                                                            co.setPricingMode(ConversionOptimizerBiddingSchemePricingMode.CONVERSIONS);
                                                                        }
                                                                    }

                                                                    if (bsConversionOptimizerChildren.item(index).getNodeName().equalsIgnoreCase("BSConvOptBidType")) {
                                                                        if (bsConversionOptimizerChildren.item(index).getTextContent().equalsIgnoreCase("T")) {
                                                                            co.setBidType(ConversionOptimizerBiddingSchemeBidType.TARGET_CPA);
                                                                        } /*else if (bsConversionOptimizerChildren.item(index).getTextContent().equalsIgnoreCase("M")) {
                                                                            co.setBidType(ConversionOptimizerBiddingSchemeBidType.MAX_CPA);
                                                                        }  */
                                                                    }
                                                                }
                                                                bsc.setBiddingScheme(co);
                                                            }

                                                        }

                                                        if (strategies.item(y).getNodeName().equalsIgnoreCase("BSManualCPC")) {

                                                            Node manualCPCNode = strategies.item(y);

                                                            NodeList manualCPCChildren = manualCPCNode.getChildNodes();

                                                            ManualCpcBiddingScheme manualCPC = new ManualCpcBiddingScheme();

                                                            for (int index = 0; index < manualCPCChildren.getLength(); index++) {

                                                                if (manualCPCChildren.item(index).getNodeName().equalsIgnoreCase("enhancedCpcEnabled")) {
                                                                    if (manualCPCChildren.item(index).getTextContent().equalsIgnoreCase("true")) {
                                                                        manualCPC.setEnhancedCpcEnabled(true);
                                                                    } else {
                                                                        manualCPC.setEnhancedCpcEnabled(false);
                                                                    }
                                                                }
                                                            }

                                                            bsc.setBiddingScheme(manualCPC);
                                                        }

                                                        if (strategies.item(y).getNodeName().equalsIgnoreCase("BSManualCPM")) {
                                                            Node manualCPMNode = strategies.item(y);

                                                            NodeList manualCPMChildren = manualCPMNode.getChildNodes();

                                                            for (int index = 0; index < manualCPMChildren.getLength(); index++) {

                                                                if (manualCPMChildren.item(index).getNodeName().equalsIgnoreCase("enable")) {
                                                                    if (manualCPMChildren.item(index).getTextContent().equalsIgnoreCase("true")) {
                                                                        bsc.setBiddingScheme(new ManualCpmBiddingScheme());
                                                                    }
                                                                }
                                                            }
                                                        }

                                                        if (strategies.item(y).getNodeName().equalsIgnoreCase("BSPercentCPA")) {
                                                            Node bsPercentCPANode = strategies.item(y);

                                                            NodeList bsPercentCPANodeChildren = bsPercentCPANode.getChildNodes();

                                                            for (int index = 0; index < bsPercentCPANodeChildren.getLength(); index++) {

                                                                if (bsPercentCPANodeChildren.item(index).getNodeName().equalsIgnoreCase("enable")) {
                                                                    if (bsPercentCPANodeChildren.item(index).getTextContent().equalsIgnoreCase("true")) {
                                                                        bsc.setBiddingScheme(new PercentCpaBiddingScheme());
                                                                    }
                                                                }
                                                            }
                                                        }

                                                        if (strategies.item(y).getNodeName().equalsIgnoreCase("BSBudgetOptimizer")) {

                                                            Node bsBudgetOptimizerNode = strategies.item(y);

                                                            NodeList bsBudgetOptimizerNodeChildren = bsBudgetOptimizerNode.getChildNodes();

                                                            BudgetOptimizerBiddingScheme bo = new BudgetOptimizerBiddingScheme();

                                                            for (int index = 0; index < bsBudgetOptimizerNodeChildren.getLength(); index++) {

                                                                if (bsBudgetOptimizerNodeChildren.item(index).getNodeName().equalsIgnoreCase("enhancedCpcEnabled")) {

                                                                    if (bsBudgetOptimizerNodeChildren.item(index).getTextContent().equalsIgnoreCase("true")) {
                                                                        bo.setEnhancedCpcEnabled(true);
                                                                    } else {
                                                                        bo.setEnhancedCpcEnabled(false);
                                                                    }
                                                                }

                                                                if (bsBudgetOptimizerNodeChildren.item(index).getNodeName().equalsIgnoreCase("bidCeiling")) {

                                                                    Money bidCeilingMoney = new Money();

                                                                    Double amount = Double.parseDouble(bsBudgetOptimizerNodeChildren.item(index).getTextContent());

                                                                    Long microAmount = (long) (amount * 10000000L / 10);
                                                                    bidCeilingMoney.setMicroAmount(microAmount);

                                                                    bo.setBidCeiling(bidCeilingMoney);
                                                                }
                                                            }

                                                            bsc.setBiddingScheme(bo);

                                                        }
                                                    }
                                                }
                                            }
                                            if (biddingStrategyConfiguration.item(a).getNodeName().equalsIgnoreCase("Bids")) {
                                                Bids bids = GetBids(biddingStrategyConfiguration.item(a).getChildNodes());
                                                if (bids != null) {
                                                    Bids[] bidsCollection = {bids};
                                                    bsc.setBids(bidsCollection);
                                                }
                                            }
                                        }
                                    }
                                    biddableCriterion.setBiddingStrategyConfiguration(bsc);
                                }
                            }

                            criterion.BiddableCriterion = biddableCriterion;

                            groupCriterions.add(criterion);
                        } else if (criterionUse.equalsIgnoreCase("N")) { // NegativeAdGroupCriterion

                            NegativeAdGroupCriterion negativeCriterion = new NegativeAdGroupCriterion();

                            for (int j = 0; j < children.getLength(); j++) {

                                if (children.item(j).getNodeName().equalsIgnoreCase("AdGroupId")) {

                                    negativeCriterion.setAdGroupId(Long.parseLong(children.item(j).getTextContent()));

                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("Keyword")) {
                                    negativeCriterion.setCriterion(GetKeywordCriterion(children.item(j).getChildNodes()));
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("UserInterest")) {
                                    negativeCriterion.setCriterion(GetUserInterestCriterion(children.item(j).getChildNodes()));
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("Placement")) {
                                    negativeCriterion.setCriterion(GetPlacementCriterion(children.item(j).getChildNodes()));
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("Vertical")) {
                                    negativeCriterion.setCriterion(GetVerticalCriterion(children.item(j).getChildNodes()));
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("Gender")) {
                                    negativeCriterion.setCriterion(GetGenderCriterion(children.item(j).getChildNodes()));
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("AgeRange")) {
                                    negativeCriterion.setCriterion(GetAgeRangeCriterion(children.item(j).getChildNodes()));
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("CampaignGxId")) {
                                    criterion.SubCampaignGxId = Long.parseLong(children.item(j).getTextContent());
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("AdGroupGxId")) {
                                    criterion.AdGroupGxId = Long.parseLong(children.item(j).getTextContent());
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("CriterionGxId")) {
                                    criterion.CriterionGxId = Long.parseLong(children.item(j).getTextContent());
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("CampaignID")) {
                                    criterion.CampaignId = Long.parseLong(children.item(j).getTextContent());
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("AdGroupId")) {
                                    criterion.AdGroupId = Long.parseLong(children.item(j).getTextContent());
                                }
                            }

                            criterion.NegativeCriterion = negativeCriterion;
                            groupCriterions.add(criterion);
                        }
                    }
                }

                ArrayList<GA_ResultItem> createdCriterions = new ArrayList<GA_ResultItem>();

                ArrayList<AdGroupCriterionOperation> ops = new ArrayList<AdGroupCriterionOperation>();

                for (GA_ResultItem kw : groupCriterions) {

                    GA_ResultItem created = new GA_ResultItem();

                    created.AdGroupGxId = kw.AdGroupGxId;
                    created.AdGroupId = kw.AdGroupId;
                    created.SubCampaignGxId = kw.SubCampaignGxId;
                    created.CampaignId = kw.CampaignId;
                    created.CriterionGxId = kw.CriterionGxId;

                    AdGroupCriterionOperation operation = new AdGroupCriterionOperation();
                    operation.setOperand(kw.NegativeCriterion == null ? kw.BiddableCriterion : kw.NegativeCriterion);
                    operation.setOperator(Operator.ADD);

                    //AdGroupCriterionOperation[] operations = new AdGroupCriterionOperation[]{operation};

                    ops.add(operation);

                }

                AdGroupCriterionOperation[] opsArray = new AdGroupCriterionOperation[]{};

                AdGroupCriterionOperation[] operations = ops.toArray(opsArray);


                AdGroupCriterionReturnValue returnValue = adGroupCriterionService.mutate(operations);

                Thread.sleep(1000);

                int j = 0;

                for (int i = 0; i < returnValue.getValue().length; i++) {

                    GA_ResultItem created = new GA_ResultItem();

                    created.AdGroupGxId = groupCriterions.get(i).AdGroupGxId;
                    created.AdGroupId = groupCriterions.get(i).AdGroupId;
                    created.SubCampaignGxId = groupCriterions.get(i).SubCampaignGxId;
                    created.CampaignId = groupCriterions.get(i).CampaignId;
                    created.CriterionGxId = groupCriterions.get(i).CriterionGxId;

                    if (returnValue.getValue(i).getCriterion() == null) {
                        created.CriterionId = 0L;
                        created.HasError = true;

                        ErrorsStruct errors = new ErrorsStruct();

                        errors.Message = returnValue.getPartialFailureErrors(j).getErrorString();

                        errors.Errors = new ArrayList<com.genexususa.eo.google.data.Error>();

                        com.genexususa.eo.google.data.Error err = new com.genexususa.eo.google.data.Error();

                        err.ErrorString = returnValue.getPartialFailureErrors(j).getErrorString();
                        err.fieldPath = returnValue.getPartialFailureErrors(j).getFieldPath();
                        //err.Reason = returnValue.getPartialFailureErrors(i). .getFaultReason();
                        err.Trigger = returnValue.getPartialFailureErrors(j).getTrigger();
                        err.Type = returnValue.getPartialFailureErrors(j).getApiErrorType();

                        j++;

                        errors.Errors.add(err);

                        created.Errors = errors;

                        createdCriterions.add(created);
                    } else {

                        created.CriterionId = returnValue.getValue(i).getCriterion().getId();

                        createdCriterions.add(created);

                    }


                }

                try {

                    JAXBContext contextObj = JAXBContext.newInstance(GA_Result.class);

                    Marshaller marshallerObj = contextObj.createMarshaller();
                    marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

                    StringWriter sw = new StringWriter();

                    res.Items = createdCriterions;

                    marshallerObj.marshal(res, sw);
                    result = sw.getBuffer().toString();

                    System.out.println(result);

                } catch (Exception exc) {
                    exc.printStackTrace();
                    result = exc.getMessage();

                }

            }

            return result;

        } catch (Exception exc) {

            GA_Result res = new GA_Result();

            ArrayList<GA_ResultItem> items = new ArrayList<GA_ResultItem>();

            GA_ResultItem error = new GA_ResultItem();

            ErrorsStruct errors = new ErrorsStruct();

            errors.Message = exc.getMessage();

            errors.Errors = new ArrayList<com.genexususa.eo.google.data.Error>();

            com.genexususa.eo.google.data.Error err = new com.genexususa.eo.google.data.Error();

            StringWriter st = new StringWriter();
            exc.printStackTrace(new PrintWriter(st));

            err.UnknownError = st.toString();

            errors.Errors.add(err);

            error.Errors = errors;

            error.HasError = true;

            items.add(error);

            String result = "";

            try {

                JAXBContext contextObj = JAXBContext.newInstance(GA_Result.class);

                Marshaller marshallerObj = contextObj.createMarshaller();
                marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

                StringWriter sw = new StringWriter();

                res.Items = items;

                marshallerObj.marshal(res, sw);
                result = sw.getBuffer().toString();
                System.out.println(result);
                return result;

            } catch (Exception ex) {
                ex.printStackTrace();
                result = ex.getMessage();
                return result;
            }
        }
    }

    public String UpdateAdGroupCriterion(String xml) {

        try {

            String result = "";

            // Get the instance of service's factory
            ServiceFactory sf = ServiceFactory.getInstance();

            // Get AdGroup Service
            AdGroupCriterionServiceInterface adGroupCriterionService = sf.GetAdGroupCriterionService(this.GetClientId());

            //GA_ResultCreateCriterion res = new GA_ResultCreateCriterion();
            GA_Result res = new GA_Result();


            Util util = new Util();

            Document doc = util.loadXMLFromString(xml);

            XPathFactory factory = XPathFactory.newInstance();
            XPath xpath = factory.newXPath();

            XPathExpression expr = xpath.compile("//GA_Criterion");

            Object criterionNodes = expr.evaluate(doc, XPathConstants.NODESET);

            NodeList criterions = (NodeList) criterionNodes;

            ArrayList<GA_ResultItem> groupCriterions = new ArrayList<GA_ResultItem>();

            if (criterions.getLength() > 0) {

                for (int i = 0; i < criterions.getLength(); i++) { // For all GA_Criterion Nodes

                    Node n = criterions.item(i);

                    NodeList children = n.getChildNodes();

                    if (children.getLength() > 0) {

                        String criterionUse = "";

                        for (int j = 0; j < children.getLength(); j++) {

                            if (children.item(j).getNodeName().equalsIgnoreCase("CriterionUse")) {
                                criterionUse = children.item(j).getTextContent();
                                break;
                            }
                        }

                        //GA_Criterion criterion = new GA_Criterion();

                        GA_ResultItem resultCriterion = new GA_ResultItem();

                        if (criterionUse.equalsIgnoreCase("B")) { // BiddableAdGroupCriterion

                            BiddableAdGroupCriterion biddableCriterion = new BiddableAdGroupCriterion();

                            Criterion criterion = null;

                            for (int j = 0; j < children.getLength(); j++) {

                                if (children.item(j).getNodeName().equalsIgnoreCase("AdGroupId")) {

                                    biddableCriterion.setAdGroupId(Long.parseLong(children.item(j).getTextContent()));

                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("CriterionId")) {
                                    resultCriterion.CriterionId = Long.parseLong(children.item(j).getTextContent());
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("CampaignGxId")) {
                                    resultCriterion.SubCampaignGxId = Long.parseLong(children.item(j).getTextContent());
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("AdGroupGxId")) {
                                    resultCriterion.AdGroupGxId = Long.parseLong(children.item(j).getTextContent());
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("CriterionGxId")) {
                                    resultCriterion.CriterionGxId = Long.parseLong(children.item(j).getTextContent());
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("CampaignID")) {
                                    resultCriterion.CampaignId = Long.parseLong(children.item(j).getTextContent());
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("AdGroupId")) {
                                    resultCriterion.AdGroupId = Long.parseLong(children.item(j).getTextContent());
                                }


                                if (children.item(j).getNodeName().equalsIgnoreCase("UserStatus")) {

                                    if (children.item(j).getTextContent().equalsIgnoreCase("A")) {
                                        biddableCriterion.setUserStatus(UserStatus.ENABLED);
                                    } else if (children.item(j).getTextContent().equalsIgnoreCase("D")) {
                                        biddableCriterion.setUserStatus(UserStatus.REMOVED);
                                    } else if (children.item(j).getTextContent().equalsIgnoreCase("P")) {
                                        biddableCriterion.setUserStatus(UserStatus.PAUSED);
                                    }
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("ServingStatus")) {

                                    if (children.item(j).getTextContent().equalsIgnoreCase("E")) {
                                        biddableCriterion.setSystemServingStatus(SystemServingStatus.ELIGIBLE);
                                    } else if (children.item(j).getTextContent().equalsIgnoreCase("RS")) {
                                        biddableCriterion.setSystemServingStatus(SystemServingStatus.RARELY_SERVED);
                                    }

                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("ApprovalStatus")) {

                                    if (children.item(j).getTextContent().equalsIgnoreCase("A")) {
                                        biddableCriterion.setApprovalStatus(ApprovalStatus.APPROVED);
                                    } else if (children.item(j).getTextContent().equalsIgnoreCase("PR")) {
                                        biddableCriterion.setApprovalStatus(ApprovalStatus.PENDING_REVIEW);
                                    } else if (children.item(j).getTextContent().equalsIgnoreCase("UR")) {
                                        biddableCriterion.setApprovalStatus(ApprovalStatus.UNDER_REVIEW);
                                    } else if (children.item(j).getTextContent().equalsIgnoreCase("D")) {
                                        biddableCriterion.setApprovalStatus(ApprovalStatus.DISAPPROVED);
                                    }
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("DisapprovalReasons")) {

                                    biddableCriterion.setDisapprovalReasons(new String[]{children.item(j).getTextContent()});
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("DestinationUrl")) {

                                    biddableCriterion.setDestinationUrl(children.item(j).getTextContent());
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("Keyword")) {
                                    criterion = GetKeywordCriterion(children.item(j).getChildNodes());
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("Placement")) {
                                    criterion = GetPlacementCriterion(children.item(j).getChildNodes());
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("Vertical")) {
                                    criterion = GetVerticalCriterion(children.item(j).getChildNodes());
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("UserInterest")) {
                                    criterion = GetUserInterestCriterion(children.item(j).getChildNodes());
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("Gender")) {
                                    criterion = GetGenderCriterion(children.item(j).getChildNodes());
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("AgeRange")) {
                                    criterion = GetAgeRangeCriterion(children.item(j).getChildNodes());
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("BiddingStrategyConfiguration")) {

                                    NodeList biddingStrategyConfiguration = children.item(j).getChildNodes();

                                    if (biddingStrategyConfiguration.getLength() > 0) {
                                        for (int a = 0; a < biddingStrategyConfiguration.getLength(); a++) {
                                            BiddingStrategyConfiguration bsc = new BiddingStrategyConfiguration();

                                            if (biddingStrategyConfiguration.item(a).getNodeName().equalsIgnoreCase("BiddingScheme")) {

                                                NodeList strategies = biddingStrategyConfiguration.item(a).getChildNodes();

                                                if (strategies.getLength() > 0) {

                                                    for (int y = 0; y < strategies.getLength(); y++) {

                                                        if (strategies.item(y).getNodeName().equalsIgnoreCase("BSConversionOptimizer")) {
                                                            Node bsConversionOptimizer = strategies.item(y);

                                                            NodeList bsConversionOptimizerChildren = bsConversionOptimizer.getChildNodes();

                                                            if (bsConversionOptimizerChildren.getLength() > 0) {

                                                                ConversionOptimizerBiddingScheme co = new ConversionOptimizerBiddingScheme();

                                                                for (int index = 0; index < bsConversionOptimizerChildren.getLength(); index++) {

                                                                    if (bsConversionOptimizerChildren.item(index).getNodeName().equalsIgnoreCase("BSConvOptPricingModel")) {
                                                                        if (bsConversionOptimizerChildren.item(index).getTextContent().equalsIgnoreCase("C")) {
                                                                            co.setPricingMode(ConversionOptimizerBiddingSchemePricingMode.CLICKS);
                                                                        } else if (bsConversionOptimizerChildren.item(index).getTextContent().equalsIgnoreCase("CN")) {
                                                                            co.setPricingMode(ConversionOptimizerBiddingSchemePricingMode.CONVERSIONS);
                                                                        }
                                                                    }

                                                                    if (bsConversionOptimizerChildren.item(index).getNodeName().equalsIgnoreCase("BSConvOptBidType")) {
                                                                        if (bsConversionOptimizerChildren.item(index).getTextContent().equalsIgnoreCase("T")) {
                                                                            co.setBidType(ConversionOptimizerBiddingSchemeBidType.TARGET_CPA);
                                                                        } /*else if (bsConversionOptimizerChildren.item(index).getTextContent().equalsIgnoreCase("M")) {
                                                                            co.setBidType(ConversionOptimizerBiddingSchemeBidType.MAX_CPA);
                                                                        }              */
                                                                    }
                                                                }
                                                                bsc.setBiddingScheme(co);
                                                            }

                                                        }

                                                        if (strategies.item(y).getNodeName().equalsIgnoreCase("BSManualCPC")) {

                                                            Node manualCPCNode = strategies.item(y);

                                                            NodeList manualCPCChildren = manualCPCNode.getChildNodes();

                                                            ManualCpcBiddingScheme manualCPC = new ManualCpcBiddingScheme();

                                                            for (int index = 0; index < manualCPCChildren.getLength(); index++) {

                                                                if (manualCPCChildren.item(index).getNodeName().equalsIgnoreCase("enhancedCpcEnabled")) {
                                                                    if (manualCPCChildren.item(index).getTextContent().equalsIgnoreCase("true")) {
                                                                        manualCPC.setEnhancedCpcEnabled(true);
                                                                    } else {
                                                                        manualCPC.setEnhancedCpcEnabled(false);
                                                                    }
                                                                }
                                                            }

                                                            bsc.setBiddingScheme(manualCPC);
                                                        }

                                                        if (strategies.item(y).getNodeName().equalsIgnoreCase("BSManualCPM")) {
                                                            Node manualCPMNode = strategies.item(y);

                                                            NodeList manualCPMChildren = manualCPMNode.getChildNodes();

                                                            for (int index = 0; index < manualCPMChildren.getLength(); index++) {

                                                                if (manualCPMChildren.item(index).getNodeName().equalsIgnoreCase("enable")) {
                                                                    if (manualCPMChildren.item(index).getTextContent().equalsIgnoreCase("true")) {
                                                                        bsc.setBiddingScheme(new ManualCpmBiddingScheme());
                                                                    }
                                                                }
                                                            }
                                                        }

                                                        if (strategies.item(y).getNodeName().equalsIgnoreCase("BSPercentCPA")) {
                                                            Node bsPercentCPANode = strategies.item(y);

                                                            NodeList bsPercentCPANodeChildren = bsPercentCPANode.getChildNodes();

                                                            for (int index = 0; index < bsPercentCPANodeChildren.getLength(); index++) {

                                                                if (bsPercentCPANodeChildren.item(index).getNodeName().equalsIgnoreCase("enable")) {
                                                                    if (bsPercentCPANodeChildren.item(index).getTextContent().equalsIgnoreCase("true")) {
                                                                        bsc.setBiddingScheme(new PercentCpaBiddingScheme());
                                                                    }
                                                                }
                                                            }
                                                        }

                                                        if (strategies.item(y).getNodeName().equalsIgnoreCase("BSBudgetOptimizer")) {

                                                            Node bsBudgetOptimizerNode = strategies.item(y);

                                                            NodeList bsBudgetOptimizerNodeChildren = bsBudgetOptimizerNode.getChildNodes();

                                                            BudgetOptimizerBiddingScheme bo = new BudgetOptimizerBiddingScheme();

                                                            for (int index = 0; index < bsBudgetOptimizerNodeChildren.getLength(); index++) {

                                                                if (bsBudgetOptimizerNodeChildren.item(index).getNodeName().equalsIgnoreCase("enhancedCpcEnabled")) {

                                                                    if (bsBudgetOptimizerNodeChildren.item(index).getTextContent().equalsIgnoreCase("true")) {
                                                                        bo.setEnhancedCpcEnabled(true);
                                                                    } else {
                                                                        bo.setEnhancedCpcEnabled(false);
                                                                    }
                                                                }

                                                                if (bsBudgetOptimizerNodeChildren.item(index).getNodeName().equalsIgnoreCase("bidCeiling")) {

                                                                    Money bidCeilingMoney = new Money();

                                                                    Double amount = Double.parseDouble(bsBudgetOptimizerNodeChildren.item(index).getTextContent());

                                                                    Long microAmount = (long) (amount * 10000000L / 10);
                                                                    bidCeilingMoney.setMicroAmount(microAmount);

                                                                    bo.setBidCeiling(bidCeilingMoney);
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            }

                                            if (children.item(j).getNodeName().equalsIgnoreCase("Bids")) {
                                                Bids bids = GetBids(children.item(j).getChildNodes());
                                                if (bids != null) {
                                                    Bids[] bidsCollection = {bids};
                                                    bsc.setBids(bidsCollection);
                                                }
                                            }

                                            biddableCriterion.setBiddingStrategyConfiguration(bsc);
                                        }
                                    }
                                }
                            }

                            if (criterion != null) {
                                criterion.setId(resultCriterion.CriterionId);
                                biddableCriterion.setCriterion(criterion);
                            }

                            resultCriterion.BiddableCriterion = biddableCriterion;

                            groupCriterions.add(resultCriterion);
                        } else if (criterionUse.equalsIgnoreCase("N")) { // NegativeAdGroupCriterion

                            NegativeAdGroupCriterion negativeCriterion = new NegativeAdGroupCriterion();

                            Criterion criterion = null;

                            for (int j = 0; j < children.getLength(); j++) {

                                if (children.item(j).getNodeName().equalsIgnoreCase("AdGroupId")) {

                                    negativeCriterion.setAdGroupId(Long.parseLong(children.item(j).getTextContent()));

                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("CriterionId")) {
                                    resultCriterion.CriterionId = Long.parseLong(children.item(j).getTextContent());

                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("Keyword")) {
                                    criterion = GetKeywordCriterion(children.item(j).getChildNodes());
                                    //negativeCriterion.setCriterion(criterion);
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("Placement")) {
                                    criterion = GetPlacementCriterion(children.item(j).getChildNodes());
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("Vertical")) {
                                    criterion = GetVerticalCriterion(children.item(j).getChildNodes());
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("UserInterest")) {
                                    criterion = GetUserInterestCriterion(children.item(j).getChildNodes());
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("Gender")) {
                                    criterion = GetGenderCriterion(children.item(j).getChildNodes());
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("AgeRange")) {
                                    criterion = GetAgeRangeCriterion(children.item(j).getChildNodes());
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("CampaignGxId")) {
                                    resultCriterion.SubCampaignGxId = Long.parseLong(children.item(j).getTextContent());
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("AdGroupGxId")) {
                                    resultCriterion.AdGroupGxId = Long.parseLong(children.item(j).getTextContent());
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("CriterionGxId")) {
                                    resultCriterion.CriterionGxId = Long.parseLong(children.item(j).getTextContent());
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("CampaignID")) {
                                    resultCriterion.CampaignId = Long.parseLong(children.item(j).getTextContent());
                                }

                                if (children.item(j).getNodeName().equalsIgnoreCase("AdGroupId")) {
                                    resultCriterion.AdGroupId = Long.parseLong(children.item(j).getTextContent());
                                }
                            }

                            if (criterion != null) {
                                criterion.setId(resultCriterion.CriterionId);
                                negativeCriterion.setCriterion(criterion);
                            }

                            resultCriterion.NegativeCriterion = negativeCriterion;
                            groupCriterions.add(resultCriterion);
                        }
                    }
                }

                ArrayList<GA_ResultItem> createdCriterions = new ArrayList<GA_ResultItem>();

                ArrayList<AdGroupCriterionOperation> ops = new ArrayList<AdGroupCriterionOperation>();

                for (GA_ResultItem kw : groupCriterions) {

                    AdGroupCriterionOperation operation = new AdGroupCriterionOperation();
                    operation.setOperand(kw.NegativeCriterion == null ? kw.BiddableCriterion : kw.NegativeCriterion);
                    operation.setOperator(Operator.SET);

                    ops.add(operation);


                }

                AdGroupCriterionOperation[] opsArray = new AdGroupCriterionOperation[]{};

                AdGroupCriterionOperation[] operations = ops.toArray(opsArray);


                AdGroupCriterionReturnValue returnValue = adGroupCriterionService.mutate(operations);

                Thread.sleep(1000);

                int j = 0;

                for (int i = 0; i < returnValue.getValue().length; i++) {

                    GA_ResultItem created = new GA_ResultItem();

                    created.AdGroupGxId = groupCriterions.get(i).AdGroupGxId;
                    created.AdGroupId = groupCriterions.get(i).AdGroupId;
                    created.SubCampaignGxId = groupCriterions.get(i).SubCampaignGxId;
                    created.CampaignId = groupCriterions.get(i).CampaignId;
                    created.CriterionGxId = groupCriterions.get(i).CriterionGxId;

                    if (returnValue.getValue(i).getCriterion() == null) {
                        created.CriterionId = 0L;
                        created.HasError = true;

                        ErrorsStruct errors = new ErrorsStruct();

                        errors.Message = returnValue.getPartialFailureErrors(j).getErrorString();

                        errors.Errors = new ArrayList<com.genexususa.eo.google.data.Error>();

                        com.genexususa.eo.google.data.Error err = new com.genexususa.eo.google.data.Error();

                        err.ErrorString = returnValue.getPartialFailureErrors(j).getErrorString();
                        err.fieldPath = returnValue.getPartialFailureErrors(j).getFieldPath();
                        //err.Reason = returnValue.getPartialFailureErrors(i). .getFaultReason();
                        err.Trigger = returnValue.getPartialFailureErrors(j).getTrigger();
                        err.Type = returnValue.getPartialFailureErrors(j).getApiErrorType();

                        j++;

                        errors.Errors.add(err);

                        created.Errors = errors;

                        createdCriterions.add(created);
                    } else {

                        created.CriterionId = returnValue.getValue(i).getCriterion().getId();

                        createdCriterions.add(created);

                    }


                }


                try {

                    JAXBContext contextObj = JAXBContext.newInstance(GA_Result.class);

                    Marshaller marshallerObj = contextObj.createMarshaller();
                    marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

                    StringWriter sw = new StringWriter();

                    res.Items = createdCriterions;

                    marshallerObj.marshal(res, sw);
                    result = sw.getBuffer().toString();

                    System.out.println(result);

                } catch (Exception exc) {
                    exc.printStackTrace();
                    result = exc.getMessage();

                }

            }


            return result;

        } catch (Exception exc) {

            GA_Result res = new GA_Result();

            ArrayList<GA_ResultItem> items = new ArrayList<GA_ResultItem>();

            GA_ResultItem error = new GA_ResultItem();

            ErrorsStruct errors = new ErrorsStruct();

            errors.Message = exc.getMessage();

            errors.Errors = new ArrayList<com.genexususa.eo.google.data.Error>();

            com.genexususa.eo.google.data.Error err = new com.genexususa.eo.google.data.Error();

            StringWriter st = new StringWriter();
            exc.printStackTrace(new PrintWriter(st));

            err.UnknownError = st.toString();

            errors.Errors.add(err);

            error.Errors = errors;

            error.HasError = true;

            items.add(error);

            String result = "";

            try {

                JAXBContext contextObj = JAXBContext.newInstance(GA_Result.class);

                Marshaller marshallerObj = contextObj.createMarshaller();
                marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

                StringWriter sw = new StringWriter();

                res.Items = items;

                marshallerObj.marshal(res, sw);
                result = sw.getBuffer().toString();
                System.out.println(result);
                return result;

            } catch (Exception ex) {
                ex.printStackTrace();
                result = ex.getMessage();
                return result;
            }
        }


    }


    public String DeleteAdGroupCriterion(Long criterionId, Long adGroupId) {

        try {


            String result = "";

            GA_Result res = new GA_Result();

            GA_ResultItem deleted = new GA_ResultItem();

            deleted.CriterionId = criterionId;
            deleted.AdGroupId = adGroupId;

            // Get the instance of service's factory
            ServiceFactory sf = ServiceFactory.getInstance();

            // Get AdGroup Service
            AdGroupCriterionServiceInterface adGroupCriterionService = sf.GetAdGroupCriterionService(this.GetClientId());


            // Create base class criterion to avoid setting criterion specific fields.
            Criterion criterion = new Criterion();
            criterion.setId(criterionId);

            // Create ad group criterion.
            AdGroupCriterion adGroupCriterion = new AdGroupCriterion();
            adGroupCriterion.setAdGroupId(adGroupId);
            adGroupCriterion.setCriterion(criterion);

            // Create operations.
            AdGroupCriterionOperation operation = new AdGroupCriterionOperation();
            operation.setOperand(adGroupCriterion);
            operation.setOperator(Operator.REMOVE);


            try {
                AdGroupCriterionOperation[] operations = new AdGroupCriterionOperation[]{operation};

                // Delete ad group criteria.
                AdGroupCriterionReturnValue resultValue = adGroupCriterionService.mutate(operations);
                Thread.sleep(1000);
                deleted.HasError = false;
                res.Items.add(deleted);
            } catch (ApiException apiException) {
                boolean retry = false;

                ApiError[] apiErrors = apiException.getErrors();

                for (ApiError error : apiErrors) {

                    if (error.getErrorString().equalsIgnoreCase("RateExceededError.RATE_EXCEEDED")) {

                        Thread.sleep(35000);


                        operation = new AdGroupCriterionOperation();
                        operation.setOperand(adGroupCriterion);
                        operation.setOperator(Operator.REMOVE);

                        AdGroupCriterionOperation[] operations = new AdGroupCriterionOperation[]{operation};

                        AdGroupCriterionReturnValue returnValue = adGroupCriterionService.mutate(operations);

                        Thread.sleep(1000);

                        //created.CriterionId = returnValue.getValue(0).getCriterion().getId();

                        //createdCriterions.add(created);

                        deleted.HasError = false;

                        retry = true;

                    }
                }

                if (!retry) {

                    //created.CriterionId= 0L;
                    deleted.AdGroupId = 0L;
                    deleted.CriterionId = 0L;
                    deleted.HasError = true;


                    for (ApiError apiError : apiErrors) {
                        ErrorsStruct errors = new ErrorsStruct();

                        errors.Message = apiError.getErrorString();

                        errors.Errors = new ArrayList<com.genexususa.eo.google.data.Error>();

                        com.genexususa.eo.google.data.Error err = new com.genexususa.eo.google.data.Error();

                        err.ErrorString = apiError.getErrorString();
                        err.fieldPath = apiError.getFieldPath();
                        err.Reason = apiException.getFaultReason();
                        err.Trigger = apiError.getTrigger();
                        err.Type = apiError.getApiErrorType();

                        errors.Errors.add(err);

                        deleted.Errors = errors;

                        res.Items.add(deleted);


                    }

                }

            }


            try {

                JAXBContext contextObj = JAXBContext.newInstance(GA_Result.class);

                Marshaller marshallerObj = contextObj.createMarshaller();
                marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

                StringWriter sw = new StringWriter();

                marshallerObj.marshal(res, sw);
                result = sw.getBuffer().toString();

                System.out.println(result);

            } catch (Exception exc) {
                exc.printStackTrace();
                result = exc.getMessage();

            }


            return result;

        } catch (Exception exc) {

            GA_Result res = new GA_Result();

            ArrayList<GA_ResultItem> items = new ArrayList<GA_ResultItem>();

            GA_ResultItem error = new GA_ResultItem();

            ErrorsStruct errors = new ErrorsStruct();

            errors.Message = exc.getMessage();

            errors.Errors = new ArrayList<com.genexususa.eo.google.data.Error>();

            com.genexususa.eo.google.data.Error err = new com.genexususa.eo.google.data.Error();

            StringWriter st = new StringWriter();
            exc.printStackTrace(new PrintWriter(st));

            err.UnknownError = st.toString();

            errors.Errors.add(err);

            error.Errors = errors;

            error.HasError = true;

            items.add(error);

            String result = "";

            try {

                JAXBContext contextObj = JAXBContext.newInstance(GA_Result.class);

                Marshaller marshallerObj = contextObj.createMarshaller();
                marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

                StringWriter sw = new StringWriter();

                res.Items = items;

                marshallerObj.marshal(res, sw);
                result = sw.getBuffer().toString();
                System.out.println(result);
                return result;

            } catch (Exception ex) {
                ex.printStackTrace();
                result = ex.getMessage();
                return result;
            }
        }
    }


    private Bids GetBids(NodeList children) {

        for (int i = 0; i < children.getLength(); i++) {

            if (children.item(i).getNodeName().equalsIgnoreCase("BudgetOptimizer")) {

                if (children.item(i).getNodeName().equalsIgnoreCase("PercentCPA")) {

                    PercentCpaBid pCpaBids = new PercentCpaBid();

                    for (int j = 0; j < children.item(i).getChildNodes().getLength(); j++) {

                        if (children.item(i).getChildNodes().item(j).getNodeName().equalsIgnoreCase("PercentCpa")) {
                            pCpaBids.setBid(Integer.parseInt(children.item(i).getChildNodes().item(j).getTextContent()));
                        }

                        if (children.item(i).getChildNodes().item(j).getNodeName().equalsIgnoreCase("BidSource")) {
                            if (children.item(i).getChildNodes().item(j).getTextContent().equalsIgnoreCase("A")) {
                                pCpaBids.setPercentCpaBidSource(BidSource.ADGROUP);
                            } else if (children.item(i).getChildNodes().item(j).getTextContent().equalsIgnoreCase("C")) {
                                pCpaBids.setPercentCpaBidSource(BidSource.CRITERION);
                            }
                        }
                    }

                    return pCpaBids;
                }

            }

            // REMOVED ON v201302

            /*
            if (children.item(i).getNodeName().equalsIgnoreCase("BudgetOptimizer")) {

                return new BudgetOptimizerAdGroupBids();
            }
            */

            if (children.item(i).getNodeName().equalsIgnoreCase("ConversionOptimizer")) {

                CpaBid cOptimizerBids = new CpaBid();

                for (int j = 0; j < children.item(i).getChildNodes().getLength(); j++) {

                    if (children.item(i).getChildNodes().item(j).getNodeName().equalsIgnoreCase("TargetCpa")) {

                        Money targetCpaMoney = new Money();

                        Double amount = Double.parseDouble(children.item(i).getChildNodes().item(j).getTextContent());

                        Long microAmount = (long) (amount * 10000000L / 10);

                        targetCpaMoney.setMicroAmount(microAmount);

                        cOptimizerBids.setBid(targetCpaMoney);

                        return cOptimizerBids;
                    }

                }
            }

            if (children.item(i).getNodeName().equalsIgnoreCase("ManualCPC")) {

                CpcBid manualCPC = new CpcBid();

                for (int j = 0; j < children.item(i).getChildNodes().getLength(); j++) {

                    if (children.item(i).getChildNodes().item(j).getNodeName().equalsIgnoreCase("MaxCpc")) {

                        Money criterionMaxMoney = new Money();

                        Double amount = Double.parseDouble(children.item(i).getChildNodes().item(j).getTextContent());

                        Long microAmount = (long) (amount * 10000000L / 10);

                        criterionMaxMoney.setMicroAmount(microAmount);

                        manualCPC.setBid(criterionMaxMoney);

                    }

                    if (children.item(i).getChildNodes().item(j).getNodeName().equalsIgnoreCase("ContentMaxCpc")) {

                        Double amount = Double.parseDouble(children.item(i).getChildNodes().item(j).getTextContent());

                        if (amount > 0) {
                            Money criterionContentMaxMoney = new Money();

                            Long microAmount = (long) (amount * 10000000L / 10);

                            criterionContentMaxMoney.setMicroAmount(microAmount);

                            manualCPC.setBid(criterionContentMaxMoney);
                        }
                    }

                    if (children.item(i).getChildNodes().item(j).getNodeName().equalsIgnoreCase("BidSource")) {
                        if (children.item(i).getChildNodes().item(j).getTextContent().equalsIgnoreCase("A")) {
                            manualCPC.setCpcBidSource(BidSource.ADGROUP);
                        } else if (children.item(i).getChildNodes().item(j).getTextContent().equalsIgnoreCase("C")) {
                            manualCPC.setCpcBidSource(BidSource.CRITERION);
                        }
                    }

                }

                return manualCPC;

            }

            if (children.item(i).getNodeName().equalsIgnoreCase("ManualCPM")) {

                CpmBid manualCPM = new CpmBid();

                for (int j = 0; j < children.item(i).getChildNodes().getLength(); j++) {

                    if (children.item(i).getChildNodes().item(j).getNodeName().equalsIgnoreCase("MaxCpm")) {

                        Money maxCPMMoney = new Money();

                        Double amount = Double.parseDouble(children.item(i).getChildNodes().item(j).getTextContent());

                        Long microAmount = (long) (amount * 10000000L / 10);

                        maxCPMMoney.setMicroAmount(microAmount);

                        manualCPM.setBid(maxCPMMoney);
                    }

                    if (children.item(i).getChildNodes().item(j).getNodeName().equalsIgnoreCase("BidSource")) {
                        if (children.item(i).getChildNodes().item(j).getTextContent().equalsIgnoreCase("A")) {
                            manualCPM.setCpmBidSource(BidSource.ADGROUP);
                        } else if (children.item(i).getChildNodes().item(j).getTextContent().equalsIgnoreCase("C")) {
                            manualCPM.setCpmBidSource(BidSource.CRITERION);
                        }
                    }

                }

                return manualCPM;

            }


        }

        return null;  //To change body of created methods use File | Settings | File Templates.
    }

    private Criterion GetKeywordCriterion(NodeList children) {

        Keyword keyword = new Keyword();

        for (int i = 0; i < children.getLength(); i++) {

            if (children.item(i).getNodeName().equalsIgnoreCase("Text")) {

                keyword.setText(children.item(i).getTextContent());
            }

            if (children.item(i).getNodeName().equalsIgnoreCase("MatchType")) {

                if (children.item(i).getTextContent().equalsIgnoreCase("E")) {
                    keyword.setMatchType(KeywordMatchType.EXACT);
                } else if (children.item(i).getTextContent().equalsIgnoreCase("P")) {
                    keyword.setMatchType(KeywordMatchType.PHRASE);
                } else if (children.item(i).getTextContent().equalsIgnoreCase("B")) {
                    keyword.setMatchType(KeywordMatchType.BROAD);
                }
            }

        }


        return keyword;  //To change body of created methods use File | Settings | File Templates.
    }

    private Criterion GetPlacementCriterion(NodeList children) {
        Placement placement = new Placement();
        for (int i = 0; i < children.getLength(); i++) {
            if (children.item(i).getNodeName().equalsIgnoreCase("Url")) {
                placement.setUrl(children.item(i).getTextContent());
            }
        }
        return placement;
    }

    private Criterion GetVerticalCriterion(NodeList children) {
        Vertical vertical = new Vertical();
        for (int i = 0; i < children.getLength(); i++) {
            if (children.item(i).getNodeName().equalsIgnoreCase("VerticalId")) {
                vertical.setVerticalId(Long.valueOf(children.item(i).getTextContent()));
            }
            if (children.item(i).getNodeName().equalsIgnoreCase("Path")) {
                List<String> pathList = new ArrayList<String>();
                NodeList pathNode = children.item(i).getChildNodes();
                for (int j = 0; j < pathNode.getLength(); j++) {
                    if (pathNode.item(j).getNodeName().equalsIgnoreCase("PathElement")) {
                        pathList.add(pathNode.item(j).getTextContent());
                    }
                }
                String[] path = new String[]{};
                pathList.toArray(path);
                vertical.setPath(path);
            }
        }
        return vertical;
    }

    private Criterion GetUserInterestCriterion(NodeList children) {
        CriterionUserInterest criterionUserInterest = new CriterionUserInterest();
        for (int i = 0; i < children.getLength(); i++) {
            if (children.item(i).getNodeName().equalsIgnoreCase("UserInterestId")) {
                criterionUserInterest.setUserInterestId(Long.valueOf(children.item(i).getTextContent()));
            }
        }
        return criterionUserInterest;
    }

    private Criterion GetGenderCriterion(NodeList children) {
        Gender gender = new Gender();
        for (int i = 0; i < children.getLength(); i++) {
            if (children.item(i).getNodeName().equalsIgnoreCase("GenderId")) {
                gender.setId(Long.valueOf(children.item(i).getTextContent()));
            }
        }
        return gender;
    }

    private Criterion GetAgeRangeCriterion(NodeList children) {
        AgeRange ageRange = new AgeRange();
        for (int i = 0; i < children.getLength(); i++) {
            if (children.item(i).getNodeName().equalsIgnoreCase("AgeRangeId")) {
                ageRange.setId(Long.valueOf(children.item(i).getTextContent()));
            }
        }
        return ageRange;
    }

    protected ArrayList<AdGroupKeywordReport> GetAdGroupKeywords(String clientId) {


        ArrayList<AdGroupKeywordReport> result = new ArrayList<AdGroupKeywordReport>();

        // Get the instance of service's factory
        ServiceFactory sf = ServiceFactory.getInstance();

        try {
            // Get AdGroup Service
            AdGroupCriterionServiceInterface adGroupCriterionService = sf.GetAdGroupCriterionService(clientId);

            int offset = 0;

            // Create selector.
            Selector selector = new Selector();
            selector.setFields(new String[]{
                    "BiddingStrategyType",
                    "CpcBid",
                    "CpmBid",
                    "CriterionUse",
                    "DestinationUrl",
                    "Id",
                    "KeywordMatchType",
                    "KeywordText",
                    "PercentCpaBid",
                    "Status"
            });
            selector.setOrdering(new OrderBy[]{new OrderBy("AdGroupId", SortOrder.ASCENDING)});
            selector.setPaging(new Paging(offset, PAGE_SIZE));

            // Create predicates.
        /*Predicate adGroupIdPredicate =
                new Predicate("AdGroupId", PredicateOperator.IN, new String[]{adGroupId.toString()});*/
            Predicate criteriaTypePredicate =
                    new Predicate("CriteriaType", PredicateOperator.EQUALS, new String[]{"KEYWORD"});
            Predicate statusPredicate = new Predicate("Status", PredicateOperator.NOT_EQUALS, new String[]{"REMOVED"});
            selector.setPredicates(new Predicate[]{criteriaTypePredicate, statusPredicate});

            AdGroupCriterionPage page = null;

            do {

                page = adGroupCriterionService.get(selector);

                if (page.getEntries() != null && page.getEntries().length > 0) {
                    // Display results.
                    for (AdGroupCriterion adGroupCriterionResult : page.getEntries()) {

                        AdGroupKeywordReport adGroupKeyword = new AdGroupKeywordReport();

                        if (adGroupCriterionResult.getCriterion() instanceof Keyword) {
                            Keyword keyword = (Keyword) adGroupCriterionResult.getCriterion();

                            adGroupKeyword.AdGroupId = adGroupCriterionResult.getAdGroupId();
                            if (adGroupCriterionResult instanceof BiddableAdGroupCriterion) {
                                if (((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.BUDGET_OPTIMIZER) {
                                    adGroupKeyword.BiddingStrategyType = "BO";
                                } else if (((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.CONVERSION_OPTIMIZER) {
                                    adGroupKeyword.BiddingStrategyType = "CO";
                                } else if (((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.MANUAL_CPC) {
                                    adGroupKeyword.BiddingStrategyType = "MCPC";
                                } else if (((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.MANUAL_CPM) {
                                    adGroupKeyword.BiddingStrategyType = "MCPM";
                                } else if (((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.PERCENT_CPA) {
                                    adGroupKeyword.BiddingStrategyType = "PCPA";
                                }

                                if (((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBids() != null) {
                                    for (Bids bid : ((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBids()) {
                                        if (bid instanceof CpcBid) {
                                            if (((CpcBid) bid).getBid() != null) {
                                                adGroupKeyword.CpcBid = (double) ((CpcBid) bid).getBid().getMicroAmount() / (double) 1000000;
                                            }
                                        } else if (bid instanceof CpmBid) {
                                            if (((CpmBid) bid).getBid() != null) {
                                                adGroupKeyword.CpmBid = (double) ((CpmBid) bid).getBid().getMicroAmount() / (double) 1000000;
                                            }
                                        } else if (bid instanceof PercentCpaBid) {
                                            adGroupKeyword.PercentCpaBid = ((PercentCpaBid) bid).getBid();
                                        }
                                    }
                                }

                                adGroupKeyword.DestinationUrl = ((BiddableAdGroupCriterion) adGroupCriterionResult).getDestinationUrl();

                                if (((BiddableAdGroupCriterion) adGroupCriterionResult).getUserStatus() == UserStatus.ENABLED) {
                                    adGroupKeyword.Status = "A";
                                } else if (((BiddableAdGroupCriterion) adGroupCriterionResult).getUserStatus() == UserStatus.PAUSED) {
                                    adGroupKeyword.Status = "P";
                                } else if (((BiddableAdGroupCriterion) adGroupCriterionResult).getUserStatus() == UserStatus.REMOVED) {
                                    adGroupKeyword.Status = "D";
                                }
                            }

                            if (adGroupCriterionResult.getCriterionUse() == CriterionUse.BIDDABLE) {
                                adGroupKeyword.CriterionUse = "B";
                            } else if (adGroupCriterionResult.getCriterionUse() == CriterionUse.NEGATIVE) {
                                adGroupKeyword.CriterionUse = "N";
                            }

                            adGroupKeyword.Id = adGroupCriterionResult.getCriterion().getId();

                            if (keyword.getMatchType() == KeywordMatchType.EXACT) {
                                adGroupKeyword.KeywordMatchType = "E";
                            } else if (keyword.getMatchType() == KeywordMatchType.PHRASE) {
                                adGroupKeyword.KeywordMatchType = "P";
                            } else if (keyword.getMatchType() == KeywordMatchType.BROAD) {
                                adGroupKeyword.KeywordMatchType = "B";
                            }

                            adGroupKeyword.KeywordText = keyword.getText();

                            result.add(adGroupKeyword);
                        }
                    }
                }


                offset += PAGE_SIZE;
                selector.getPaging().setStartIndex(offset);

            } while (offset < page.getTotalNumEntries());


        } catch (Exception exc) {
            exc.printStackTrace(System.out);
        }

        return result;
    }

    protected ArrayList<AdGroupKeywordReport> GetAdGroupKeywordsWithRemoved(String clientId) {


        ArrayList<AdGroupKeywordReport> result = new ArrayList<AdGroupKeywordReport>();

        // Get the instance of service's factory
        ServiceFactory sf = ServiceFactory.getInstance();

        try {
            // Get AdGroup Service
            AdGroupCriterionServiceInterface adGroupCriterionService = sf.GetAdGroupCriterionService(clientId);

            int offset = 0;

            // Create selector.
            Selector selector = new Selector();
            selector.setFields(new String[]{
                    "BiddingStrategyType",
                    "CpcBid",
                    "CpmBid",
                    "CriterionUse",
                    "DestinationUrl",
                    "Id",
                    "KeywordMatchType",
                    "KeywordText",
                    "PercentCpaBid",
                    "Status"
            });
            selector.setOrdering(new OrderBy[]{new OrderBy("AdGroupId", SortOrder.ASCENDING)});
            selector.setPaging(new Paging(offset, PAGE_SIZE));

            // Create predicates.
        /*Predicate adGroupIdPredicate =
                new Predicate("AdGroupId", PredicateOperator.IN, new String[]{adGroupId.toString()});*/
            Predicate criteriaTypePredicate =
                    new Predicate("CriteriaType", PredicateOperator.EQUALS, new String[]{"KEYWORD"});
            //Predicate statusPredicate = new Predicate("Status", PredicateOperator.NOT_EQUALS, new String[]{"REMOVED"});
            selector.setPredicates(new Predicate[]{criteriaTypePredicate});

            AdGroupCriterionPage page = null;

            do {

                page = adGroupCriterionService.get(selector);

                if (page.getEntries() != null && page.getEntries().length > 0) {
                    // Display results.
                    for (AdGroupCriterion adGroupCriterionResult : page.getEntries()) {

                        AdGroupKeywordReport adGroupKeyword = new AdGroupKeywordReport();

                        if (adGroupCriterionResult.getCriterion() instanceof Keyword) {
                            Keyword keyword = (Keyword) adGroupCriterionResult.getCriterion();

                            adGroupKeyword.AdGroupId = adGroupCriterionResult.getAdGroupId();
                            if (adGroupCriterionResult instanceof BiddableAdGroupCriterion) {
                                if (((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.BUDGET_OPTIMIZER) {
                                    adGroupKeyword.BiddingStrategyType = "BO";
                                } else if (((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.CONVERSION_OPTIMIZER) {
                                    adGroupKeyword.BiddingStrategyType = "CO";
                                } else if (((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.MANUAL_CPC) {
                                    adGroupKeyword.BiddingStrategyType = "MCPC";
                                } else if (((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.MANUAL_CPM) {
                                    adGroupKeyword.BiddingStrategyType = "MCPM";
                                } else if (((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.PERCENT_CPA) {
                                    adGroupKeyword.BiddingStrategyType = "PCPA";
                                }

                                if (((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBids() != null) {
                                    for (Bids bid : ((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBids()) {
                                        if (bid instanceof CpcBid) {
                                            if (((CpcBid) bid).getBid() != null) {
                                                adGroupKeyword.CpcBid = (double) ((CpcBid) bid).getBid().getMicroAmount() / (double) 1000000;
                                            }
                                        } else if (bid instanceof CpmBid) {
                                            if (((CpmBid) bid).getBid() != null) {
                                                adGroupKeyword.CpmBid = (double) ((CpmBid) bid).getBid().getMicroAmount() / (double) 1000000;
                                            }
                                        } else if (bid instanceof PercentCpaBid) {
                                            adGroupKeyword.PercentCpaBid = ((PercentCpaBid) bid).getBid();
                                        }
                                    }
                                }

                                adGroupKeyword.DestinationUrl = ((BiddableAdGroupCriterion) adGroupCriterionResult).getDestinationUrl();

                                if (((BiddableAdGroupCriterion) adGroupCriterionResult).getUserStatus() == UserStatus.ENABLED) {
                                    adGroupKeyword.Status = "A";
                                } else if (((BiddableAdGroupCriterion) adGroupCriterionResult).getUserStatus() == UserStatus.PAUSED) {
                                    adGroupKeyword.Status = "P";
                                } else if (((BiddableAdGroupCriterion) adGroupCriterionResult).getUserStatus() == UserStatus.REMOVED) {
                                    adGroupKeyword.Status = "D";
                                }
                            }

                            if (adGroupCriterionResult.getCriterionUse() == CriterionUse.BIDDABLE) {
                                adGroupKeyword.CriterionUse = "B";
                            } else if (adGroupCriterionResult.getCriterionUse() == CriterionUse.NEGATIVE) {
                                adGroupKeyword.CriterionUse = "N";
                            }

                            adGroupKeyword.Id = adGroupCriterionResult.getCriterion().getId();

                            if (keyword.getMatchType() == KeywordMatchType.EXACT) {
                                adGroupKeyword.KeywordMatchType = "E";
                            } else if (keyword.getMatchType() == KeywordMatchType.PHRASE) {
                                adGroupKeyword.KeywordMatchType = "P";
                            } else if (keyword.getMatchType() == KeywordMatchType.BROAD) {
                                adGroupKeyword.KeywordMatchType = "B";
                            }

                            adGroupKeyword.KeywordText = keyword.getText();

                            result.add(adGroupKeyword);
                        }
                    }
                }


                offset += PAGE_SIZE;
                selector.getPaging().setStartIndex(offset);

            } while (offset < page.getTotalNumEntries());


        } catch (Exception exc) {
            exc.printStackTrace(System.out);
        }

        return result;
    }

    protected ArrayList<AdGroupPlacementReport> GetAdGroupPlacements(String clientId) {


        ArrayList<AdGroupPlacementReport> result = new ArrayList<AdGroupPlacementReport>();

        // Get the instance of service's factory
        ServiceFactory sf = ServiceFactory.getInstance();

        try {
            // Get AdGroup Service
            AdGroupCriterionServiceInterface adGroupCriterionService = sf.GetAdGroupCriterionService(clientId);

            int offset = 0;

            // Create selector.
            Selector selector = new Selector();
            selector.setFields(new String[]{
                    "BiddingStrategyType",
                    "CpcBid",
                    "CpmBid",
                    "CriterionUse",
                    "DestinationUrl",
                    "Id",
                    "PlacementUrl",
                    "PercentCpaBid",
                    "Status"
            });
            selector.setOrdering(new OrderBy[]{new OrderBy("AdGroupId", SortOrder.ASCENDING)});
            selector.setPaging(new Paging(offset, PAGE_SIZE));

            // Create predicates.
        /*Predicate adGroupIdPredicate =
                new Predicate("AdGroupId", PredicateOperator.IN, new String[]{adGroupId.toString()});*/
            Predicate criteriaTypePredicate =
                    new Predicate("CriteriaType", PredicateOperator.EQUALS, new String[]{"PLACEMENT"});
            selector.setPredicates(new Predicate[]{criteriaTypePredicate});

            AdGroupCriterionPage page = null;

            do {

                page = adGroupCriterionService.get(selector);

                if (page.getEntries() != null && page.getEntries().length > 0) {
                    // Display results.
                    for (AdGroupCriterion adGroupCriterionResult : page.getEntries()) {

                        AdGroupPlacementReport adGroupPlacement = new AdGroupPlacementReport();
                        adGroupPlacement.AdGroupId = adGroupCriterionResult.getAdGroupId();

                        if (adGroupCriterionResult.getCriterion() instanceof Placement) {
                            Placement placement = (Placement) adGroupCriterionResult.getCriterion();

                            if (adGroupCriterionResult instanceof BiddableAdGroupCriterion) {
                                if (((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.BUDGET_OPTIMIZER) {
                                    adGroupPlacement.BiddingStrategyType = "BO";
                                } else if (((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.CONVERSION_OPTIMIZER) {
                                    adGroupPlacement.BiddingStrategyType = "CO";
                                } else if (((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.MANUAL_CPC) {
                                    adGroupPlacement.BiddingStrategyType = "MCPC";
                                } else if (((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.MANUAL_CPM) {
                                    adGroupPlacement.BiddingStrategyType = "MCPM";
                                } else if (((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.PERCENT_CPA) {
                                    adGroupPlacement.BiddingStrategyType = "PCPA";
                                }

                                if (((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBids() != null) {
                                    for (Bids bid : ((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBids()) {
                                        if (bid instanceof CpcBid) {
                                            if (((CpcBid) bid).getBid() != null) {
                                                adGroupPlacement.CpcBid = (double) ((CpcBid) bid).getBid().getMicroAmount() / (double) 1000000;
                                            }
                                        } else if (bid instanceof CpmBid) {
                                            if (((CpmBid) bid).getBid() != null) {
                                                adGroupPlacement.CpmBid = (double) ((CpmBid) bid).getBid().getMicroAmount() / (double) 1000000;
                                            }
                                        } else if (bid instanceof PercentCpaBid) {
                                            adGroupPlacement.PercentCpaBid = ((PercentCpaBid) bid).getBid();
                                        }
                                    }
                                }

                                adGroupPlacement.DestinationUrl = ((BiddableAdGroupCriterion) adGroupCriterionResult).getDestinationUrl();

                                if (((BiddableAdGroupCriterion) adGroupCriterionResult).getUserStatus() == UserStatus.ENABLED) {
                                    adGroupPlacement.Status = "A";
                                } else if (((BiddableAdGroupCriterion) adGroupCriterionResult).getUserStatus() == UserStatus.PAUSED) {
                                    adGroupPlacement.Status = "P";
                                } else if (((BiddableAdGroupCriterion) adGroupCriterionResult).getUserStatus() == UserStatus.REMOVED) {
                                    adGroupPlacement.Status = "D";
                                }
                            }

                            if (adGroupCriterionResult.getCriterionUse() == CriterionUse.BIDDABLE) {
                                adGroupPlacement.CriterionUse = "B";
                            } else if (adGroupCriterionResult.getCriterionUse() == CriterionUse.NEGATIVE) {
                                adGroupPlacement.CriterionUse = "N";
                            }

                            adGroupPlacement.Id = adGroupCriterionResult.getCriterion().getId();

                            adGroupPlacement.PlacementUrl = placement.getUrl();

                            result.add(adGroupPlacement);
                        }
                    }
                }


                offset += PAGE_SIZE;
                selector.getPaging().setStartIndex(offset);

            } while (offset < page.getTotalNumEntries());


        } catch (Exception exc) {
            exc.printStackTrace(System.out);
        }

        return result;
    }

    protected ArrayList<AdGroupTopicReport> GetAdGroupTopics(String clientId) {


        ArrayList<AdGroupTopicReport> result = new ArrayList<AdGroupTopicReport>();

        // Get the instance of service's factory
        ServiceFactory sf = ServiceFactory.getInstance();

        try {
            // Get AdGroup Service
            AdGroupCriterionServiceInterface adGroupCriterionService = sf.GetAdGroupCriterionService(clientId);

            int offset = 0;

            // Create selector.
            Selector selector = new Selector();
            selector.setFields(new String[]{
                    "BiddingStrategyType",
                    "CpcBid",
                    "CpmBid",
                    "CriterionUse",
                    "DestinationUrl",
                    "Id",
                    "VerticalId",
                    "VerticalParentId",
                    "Path",
                    "PercentCpaBid",
                    "Status"
            });
            selector.setOrdering(new OrderBy[]{new OrderBy("AdGroupId", SortOrder.ASCENDING)});
            selector.setPaging(new Paging(offset, PAGE_SIZE));

            // Create predicates.
        /*Predicate adGroupIdPredicate =
                new Predicate("AdGroupId", PredicateOperator.IN, new String[]{adGroupId.toString()});*/
            Predicate criteriaTypePredicate =
                    new Predicate("CriteriaType", PredicateOperator.EQUALS, new String[]{"VERTICAL"});
            selector.setPredicates(new Predicate[]{criteriaTypePredicate});

            AdGroupCriterionPage page = null;

            do {

                page = adGroupCriterionService.get(selector);

                if (page.getEntries() != null && page.getEntries().length > 0) {
                    // Display results.
                    for (AdGroupCriterion adGroupCriterionResult : page.getEntries()) {

                        AdGroupTopicReport adGroupTopic = new AdGroupTopicReport();

                        adGroupTopic.AdGroupId = adGroupCriterionResult.getAdGroupId();

                        if (adGroupCriterionResult.getCriterion() instanceof Vertical) {
                            Vertical vertical = (Vertical) adGroupCriterionResult.getCriterion();

                            if (adGroupCriterionResult instanceof BiddableAdGroupCriterion) {
                                if (((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.BUDGET_OPTIMIZER) {
                                    adGroupTopic.BiddingStrategyType = "BO";
                                } else if (((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.CONVERSION_OPTIMIZER) {
                                    adGroupTopic.BiddingStrategyType = "CO";
                                } else if (((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.MANUAL_CPC) {
                                    adGroupTopic.BiddingStrategyType = "MCPC";
                                } else if (((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.MANUAL_CPM) {
                                    adGroupTopic.BiddingStrategyType = "MCPM";
                                } else if (((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.PERCENT_CPA) {
                                    adGroupTopic.BiddingStrategyType = "PCPA";
                                }

                                if (((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBids() != null) {
                                    for (Bids bid : ((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBids()) {
                                        if (bid instanceof CpcBid) {
                                            if (((CpcBid) bid).getBid() != null) {
                                                adGroupTopic.CpcBid = (double) ((CpcBid) bid).getBid().getMicroAmount() / (double) 1000000;
                                            }
                                        } else if (bid instanceof CpmBid) {
                                            if (((CpmBid) bid).getBid() != null) {
                                                adGroupTopic.CpmBid = (double) ((CpmBid) bid).getBid().getMicroAmount() / (double) 1000000;
                                            }
                                        } else if (bid instanceof PercentCpaBid) {
                                            adGroupTopic.PercentCpaBid = ((PercentCpaBid) bid).getBid();
                                        }
                                    }
                                }

                                adGroupTopic.DestinationUrl = ((BiddableAdGroupCriterion) adGroupCriterionResult).getDestinationUrl();

                                if (((BiddableAdGroupCriterion) adGroupCriterionResult).getUserStatus() == UserStatus.ENABLED) {
                                    adGroupTopic.Status = "A";
                                } else if (((BiddableAdGroupCriterion) adGroupCriterionResult).getUserStatus() == UserStatus.PAUSED) {
                                    adGroupTopic.Status = "P";
                                } else if (((BiddableAdGroupCriterion) adGroupCriterionResult).getUserStatus() == UserStatus.REMOVED) {
                                    adGroupTopic.Status = "D";
                                }
                            }

                            if (adGroupCriterionResult.getCriterionUse() == CriterionUse.BIDDABLE) {
                                adGroupTopic.CriterionUse = "B";
                            } else if (adGroupCriterionResult.getCriterionUse() == CriterionUse.NEGATIVE) {
                                adGroupTopic.CriterionUse = "N";
                            }

                            adGroupTopic.Id = adGroupCriterionResult.getCriterion().getId();

                            adGroupTopic.VerticalId = vertical.getVerticalId();

                            result.add(adGroupTopic);
                        }
                    }
                }


                offset += PAGE_SIZE;
                selector.getPaging().setStartIndex(offset);

            } while (offset < page.getTotalNumEntries());


        } catch (Exception exc) {
            exc.printStackTrace(System.out);
        }

        return result;
    }

    protected ArrayList<AdGroupInterestReport> GetAdGroupInterests(String clientId) {


        ArrayList<AdGroupInterestReport> result = new ArrayList<AdGroupInterestReport>();

        // Get the instance of service's factory
        ServiceFactory sf = ServiceFactory.getInstance();

        try {
            // Get AdGroup Service
            AdGroupCriterionServiceInterface adGroupCriterionService = sf.GetAdGroupCriterionService(clientId);

            int offset = 0;

            // Create selector.
            Selector selector = new Selector();
            selector.setFields(new String[]{
                    "BiddingStrategyType",
                    "CpcBid",
                    "CpmBid",
                    "CriterionUse",
                    "DestinationUrl",
                    "Id",
                    "UserInterestId",
                    "UserInterestName",
                    "PercentCpaBid",
                    "Status"
            });
            selector.setOrdering(new OrderBy[]{new OrderBy("AdGroupId", SortOrder.ASCENDING)});
            selector.setPaging(new Paging(offset, PAGE_SIZE));

            // Create predicates.
        /*Predicate adGroupIdPredicate =
                new Predicate("AdGroupId", PredicateOperator.IN, new String[]{adGroupId.toString()});*/
            Predicate criteriaTypePredicate =
                    new Predicate("CriteriaType", PredicateOperator.EQUALS, new String[]{"USER_INTEREST"});
            selector.setPredicates(new Predicate[]{criteriaTypePredicate});

            AdGroupCriterionPage page = null;

            do {

                page = adGroupCriterionService.get(selector);

                if (page.getEntries() != null && page.getEntries().length > 0) {
                    // Display results.
                    for (AdGroupCriterion adGroupCriterionResult : page.getEntries()) {

                        AdGroupInterestReport adGroupInterest = new AdGroupInterestReport();
                        adGroupInterest.AdGroupId = adGroupCriterionResult.getAdGroupId();

                        if (adGroupCriterionResult.getCriterion() instanceof CriterionUserInterest) {
                            CriterionUserInterest userInterest = (CriterionUserInterest) adGroupCriterionResult.getCriterion();

                            if (adGroupCriterionResult instanceof BiddableAdGroupCriterion) {
                                if (((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.BUDGET_OPTIMIZER) {
                                    adGroupInterest.BiddingStrategyType = "BO";
                                } else if (((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.CONVERSION_OPTIMIZER) {
                                    adGroupInterest.BiddingStrategyType = "CO";
                                } else if (((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.MANUAL_CPC) {
                                    adGroupInterest.BiddingStrategyType = "MCPC";
                                } else if (((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.MANUAL_CPM) {
                                    adGroupInterest.BiddingStrategyType = "MCPM";
                                } else if (((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.PERCENT_CPA) {
                                    adGroupInterest.BiddingStrategyType = "PCPA";
                                }

                                if (((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBids() != null) {
                                    for (Bids bid : ((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBids()) {
                                        if (bid instanceof CpcBid) {
                                            if (((CpcBid) bid).getBid() != null) {
                                                adGroupInterest.CpcBid = (double) ((CpcBid) bid).getBid().getMicroAmount() / (double) 1000000;
                                            }
                                        } else if (bid instanceof CpmBid) {
                                            if (((CpmBid) bid).getBid() != null) {
                                                adGroupInterest.CpmBid = (double) ((CpmBid) bid).getBid().getMicroAmount() / (double) 1000000;
                                            }
                                        } else if (bid instanceof PercentCpaBid) {
                                            adGroupInterest.PercentCpaBid = ((PercentCpaBid) bid).getBid();
                                        }
                                    }
                                }

                                adGroupInterest.DestinationUrl = ((BiddableAdGroupCriterion) adGroupCriterionResult).getDestinationUrl();

                                if (((BiddableAdGroupCriterion) adGroupCriterionResult).getUserStatus() == UserStatus.ENABLED) {
                                    adGroupInterest.Status = "A";
                                } else if (((BiddableAdGroupCriterion) adGroupCriterionResult).getUserStatus() == UserStatus.PAUSED) {
                                    adGroupInterest.Status = "P";
                                } else if (((BiddableAdGroupCriterion) adGroupCriterionResult).getUserStatus() == UserStatus.REMOVED) {
                                    adGroupInterest.Status = "D";
                                }
                            }

                            if (adGroupCriterionResult.getCriterionUse() == CriterionUse.BIDDABLE) {
                                adGroupInterest.CriterionUse = "B";
                            } else if (adGroupCriterionResult.getCriterionUse() == CriterionUse.NEGATIVE) {
                                adGroupInterest.CriterionUse = "N";
                            }

                            adGroupInterest.Id = adGroupCriterionResult.getCriterion().getId();

                            adGroupInterest.UserInterestId = userInterest.getUserInterestId();

                            result.add(adGroupInterest);
                        }
                    }
                }


                offset += PAGE_SIZE;
                selector.getPaging().setStartIndex(offset);

            } while (offset < page.getTotalNumEntries());


        } catch (Exception exc) {
            exc.printStackTrace(System.out);
        }

        return result;
    }

    protected ArrayList<AdGroupGenderReport> GetAdGroupGenders(String clientId) {


        ArrayList<AdGroupGenderReport> result = new ArrayList<AdGroupGenderReport>();

        // Get the instance of service's factory
        ServiceFactory sf = ServiceFactory.getInstance();

        try {
            // Get AdGroup Service
            AdGroupCriterionServiceInterface adGroupCriterionService = sf.GetAdGroupCriterionService(clientId);

            int offset = 0;

            // Create selector.
            Selector selector = new Selector();
            selector.setFields(new String[]{
                    "BiddingStrategyType",
                    "CpcBid",
                    "CpmBid",
                    "CriterionUse",
                    "DestinationUrl",
                    "Id",
                    "GenderType",
                    "PercentCpaBid",
                    "Status"
            });
            selector.setOrdering(new OrderBy[]{new OrderBy("AdGroupId", SortOrder.ASCENDING)});
            selector.setPaging(new Paging(offset, PAGE_SIZE));

            // Create predicates.
        /*Predicate adGroupIdPredicate =
                new Predicate("AdGroupId", PredicateOperator.IN, new String[]{adGroupId.toString()});*/
            Predicate criteriaTypePredicate =
                    new Predicate("CriteriaType", PredicateOperator.EQUALS, new String[]{"GENDER"});
            selector.setPredicates(new Predicate[]{criteriaTypePredicate});

            AdGroupCriterionPage page = null;

            do {

                page = adGroupCriterionService.get(selector);

                if (page.getEntries() != null && page.getEntries().length > 0) {
                    // Display results.
                    for (AdGroupCriterion adGroupCriterionResult : page.getEntries()) {

                        AdGroupGenderReport adGroupGender = new AdGroupGenderReport();
                        adGroupGender.AdGroupId = adGroupCriterionResult.getAdGroupId();

                        if (adGroupCriterionResult.getCriterion() instanceof Gender) {
                            Gender gender = (Gender) adGroupCriterionResult.getCriterion();

                            if (adGroupCriterionResult instanceof BiddableAdGroupCriterion) {
                                if (((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.BUDGET_OPTIMIZER) {
                                    adGroupGender.BiddingStrategyType = "BO";
                                } else if (((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.CONVERSION_OPTIMIZER) {
                                    adGroupGender.BiddingStrategyType = "CO";
                                } else if (((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.MANUAL_CPC) {
                                    adGroupGender.BiddingStrategyType = "MCPC";
                                } else if (((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.MANUAL_CPM) {
                                    adGroupGender.BiddingStrategyType = "MCPM";
                                } else if (((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.PERCENT_CPA) {
                                    adGroupGender.BiddingStrategyType = "PCPA";
                                }

                                if (((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBids() != null) {
                                    for (Bids bid : ((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBids()) {
                                        if (bid instanceof CpcBid) {
                                            if (((CpcBid) bid).getBid() != null) {
                                                adGroupGender.CpcBid = (double) ((CpcBid) bid).getBid().getMicroAmount() / (double) 1000000;
                                            }
                                        } else if (bid instanceof CpmBid) {
                                            if (((CpmBid) bid).getBid() != null) {
                                                adGroupGender.CpmBid = (double) ((CpmBid) bid).getBid().getMicroAmount() / (double) 1000000;
                                            }
                                        } else if (bid instanceof PercentCpaBid) {
                                            adGroupGender.PercentCpaBid = ((PercentCpaBid) bid).getBid();
                                        }
                                    }
                                }

                                adGroupGender.DestinationUrl = ((BiddableAdGroupCriterion) adGroupCriterionResult).getDestinationUrl();

                                if (((BiddableAdGroupCriterion) adGroupCriterionResult).getUserStatus() == UserStatus.ENABLED) {
                                    adGroupGender.Status = "A";
                                } else if (((BiddableAdGroupCriterion) adGroupCriterionResult).getUserStatus() == UserStatus.PAUSED) {
                                    adGroupGender.Status = "P";
                                } else if (((BiddableAdGroupCriterion) adGroupCriterionResult).getUserStatus() == UserStatus.REMOVED) {
                                    adGroupGender.Status = "D";
                                }
                            }

                            if (adGroupCriterionResult.getCriterionUse() == CriterionUse.BIDDABLE) {
                                adGroupGender.CriterionUse = "B";
                            } else if (adGroupCriterionResult.getCriterionUse() == CriterionUse.NEGATIVE) {
                                adGroupGender.CriterionUse = "N";
                            }

                            adGroupGender.Id = adGroupCriterionResult.getCriterion().getId();

                            adGroupGender.GenderType = gender.getGenderType().getValue();

                            result.add(adGroupGender);
                        }
                    }
                }


                offset += PAGE_SIZE;
                selector.getPaging().setStartIndex(offset);

            } while (offset < page.getTotalNumEntries());


        } catch (Exception exc) {
            exc.printStackTrace(System.out);
        }

        return result;
    }

    protected ArrayList<AdGroupAgeReport> GetAdGroupAges(String clientId) {


        ArrayList<AdGroupAgeReport> result = new ArrayList<AdGroupAgeReport>();

        // Get the instance of service's factory
        ServiceFactory sf = ServiceFactory.getInstance();

        try {
            // Get AdGroup Service
            AdGroupCriterionServiceInterface adGroupCriterionService = sf.GetAdGroupCriterionService(clientId);

            int offset = 0;

            // Create selector.
            Selector selector = new Selector();
            selector.setFields(new String[]{
                    "BiddingStrategyType",
                    "CpcBid",
                    "CpmBid",
                    "CriterionUse",
                    "DestinationUrl",
                    "Id",
                    "AgeRangeType",
                    "PercentCpaBid",
                    "Status"
            });
            selector.setOrdering(new OrderBy[]{new OrderBy("AdGroupId", SortOrder.ASCENDING)});
            selector.setPaging(new Paging(offset, PAGE_SIZE));

            // Create predicates.
        /*Predicate adGroupIdPredicate =
                new Predicate("AdGroupId", PredicateOperator.IN, new String[]{adGroupId.toString()});*/
            Predicate criteriaTypePredicate =
                    new Predicate("CriteriaType", PredicateOperator.EQUALS, new String[]{"AGE_RANGE"});
            selector.setPredicates(new Predicate[]{criteriaTypePredicate});

            AdGroupCriterionPage page = null;

            do {

                page = adGroupCriterionService.get(selector);

                if (page.getEntries() != null && page.getEntries().length > 0) {
                    // Display results.
                    for (AdGroupCriterion adGroupCriterionResult : page.getEntries()) {

                        AdGroupAgeReport adGroupAge = new AdGroupAgeReport();
                        adGroupAge.AdGroupId = adGroupCriterionResult.getAdGroupId();

                        if (adGroupCriterionResult.getCriterion() instanceof AgeRange) {
                            AgeRange ageRange = (AgeRange) adGroupCriterionResult.getCriterion();

                            if (adGroupCriterionResult instanceof BiddableAdGroupCriterion) {
                                if (((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.BUDGET_OPTIMIZER) {
                                    adGroupAge.BiddingStrategyType = "BO";
                                } else if (((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.CONVERSION_OPTIMIZER) {
                                    adGroupAge.BiddingStrategyType = "CO";
                                } else if (((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.MANUAL_CPC) {
                                    adGroupAge.BiddingStrategyType = "MCPC";
                                } else if (((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.MANUAL_CPM) {
                                    adGroupAge.BiddingStrategyType = "MCPM";
                                } else if (((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBiddingStrategyType() == BiddingStrategyType.PERCENT_CPA) {
                                    adGroupAge.BiddingStrategyType = "PCPA";
                                }

                                if (((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBids() != null) {
                                    for (Bids bid : ((BiddableAdGroupCriterion) adGroupCriterionResult).getBiddingStrategyConfiguration().getBids()) {
                                        if (bid instanceof CpcBid) {
                                            if (((CpcBid) bid).getBid() != null) {
                                                adGroupAge.CpcBid = (double) ((CpcBid) bid).getBid().getMicroAmount() / (double) 1000000;
                                            }
                                        } else if (bid instanceof CpmBid) {
                                            if (((CpmBid) bid).getBid() != null) {
                                                adGroupAge.CpmBid = (double) ((CpmBid) bid).getBid().getMicroAmount() / (double) 1000000;
                                            }
                                        } else if (bid instanceof PercentCpaBid) {
                                            adGroupAge.PercentCpaBid = ((PercentCpaBid) bid).getBid();
                                        }
                                    }
                                }

                                adGroupAge.DestinationUrl = ((BiddableAdGroupCriterion) adGroupCriterionResult).getDestinationUrl();

                                if (((BiddableAdGroupCriterion) adGroupCriterionResult).getUserStatus() == UserStatus.ENABLED) {
                                    adGroupAge.Status = "A";
                                } else if (((BiddableAdGroupCriterion) adGroupCriterionResult).getUserStatus() == UserStatus.PAUSED) {
                                    adGroupAge.Status = "P";
                                } else if (((BiddableAdGroupCriterion) adGroupCriterionResult).getUserStatus() == UserStatus.REMOVED) {
                                    adGroupAge.Status = "D";
                                }
                            }

                            if (adGroupCriterionResult.getCriterionUse() == CriterionUse.BIDDABLE) {
                                adGroupAge.CriterionUse = "B";
                            } else if (adGroupCriterionResult.getCriterionUse() == CriterionUse.NEGATIVE) {
                                adGroupAge.CriterionUse = "N";
                            }

                            adGroupAge.Id = adGroupCriterionResult.getCriterion().getId();

                            adGroupAge.AgeRangeType = ageRange.getAgeRangeType().getValue();

                            result.add(adGroupAge);
                        }
                    }
                }


                offset += PAGE_SIZE;
                selector.getPaging().setStartIndex(offset);

            } while (offset < page.getTotalNumEntries());


        } catch (Exception exc) {
            exc.printStackTrace(System.out);
        }

        return result;
    }

    public void GetTopKeywords(String accountId, int keywordsQty, String startDate, String endDate, String location) {

        try {
            Credential oAuth2Credential = new OfflineCredentials.Builder()
                    .forApi(OfflineCredentials.Api.ADWORDS)
                    .fromFile()
                    .build()
                    .generateCredential();

            AdWordsSession session = new AdWordsSession.Builder()
                    .fromFile()
                    .withOAuth2Credential(oAuth2Credential)
                    .build();
            session.setClientCustomerId(accountId);

            com.google.api.ads.adwords.lib.jaxb.v201406.Selector selector = new com.google.api.ads.adwords.lib.jaxb.v201406.Selector();

            selector.getFields().addAll(Lists.newArrayList(
                    "AdGroupId",
                    "AveragePosition",
                    "CampaignId",
                    "Clicks",
                    "Conversions",
                    "ConversionsManyPerClick",
                    "Cost",
                    "ExternalCustomerId",
                    "Id",
                    "Impressions",
                    "ViewThroughConversions"

            ));

            com.google.api.ads.adwords.lib.jaxb.v201406.DateRange dateRange = new com.google.api.ads.adwords.lib.jaxb.v201406.DateRange();
            dateRange.setMax(endDate.replaceAll("-", ""));
            dateRange.setMin(startDate.replaceAll("-", ""));
            selector.setDateRange(dateRange);

            String query = "SELECT AdGroupId, AveragePosition, CampaignId, Clicks, Conversions, " +
                    "ConversionsManyPerClick, Cost, ExternalCustomerId, Id, Impressions, ViewThroughConversions " +
                    "FROM KEYWORDS_PERFORMANCE_REPORT " +
                    "DURING " + startDate + "," + endDate + " "; /*+
                    "ORDER BY Clicks DESC" + " "; +
                    "LIMIT 0," + keywordsQty;*/

            // Location to download report to.
            String reportFile = location + File.separatorChar + "TOP_KEYWORDS-" + startDate + "_" + endDate + ".xml";


            // Create report definition.
            ReportDefinition reportDefinition = new ReportDefinition();
            reportDefinition.setReportName("Top " + keywordsQty + " Performing Keywords");


            ReportDownloadResponse response =
                    new ReportDownloader(session).downloadReport(query, DownloadFormat.XML);

            FileOutputStream fos = new FileOutputStream(new File(reportFile));
            Streams.copy(response.getInputStream(), fos);
            fos.close();

            String file = readFile(reportFile);

            Util util = new Util();

            Document doc = util.loadXMLFromString(file);

            XPathFactory factory = XPathFactory.newInstance();
            XPath xpath = factory.newXPath();

            XPathExpression expr = xpath.compile("//row");

            Object rowsObject = expr.evaluate(doc, XPathConstants.NODESET);
            NodeList rows = (NodeList) rowsObject;

            if (rows.getLength() > 0){

                ArrayList<Node> nodes = new ArrayList<Node>();

                for (int i = 0; i < rows.getLength(); i++){
                    Node row = rows.item(i);

                    NamedNodeMap map = row.getAttributes();
                    if (Integer.parseInt(map.getNamedItem("clicks").getNodeValue()) > 0){
                        nodes.add(row);
                    }


                }



                //System.out.println(file);

            }




        } catch (ConfigurationLoadException e) {
            e.printStackTrace();

        } catch (IOException e) {
            e.printStackTrace();
        } catch (OAuthException e) {
            e.printStackTrace();
        } catch (ReportException e) {
            e.printStackTrace();
        } catch (ReportDownloadResponseException e) {
            e.printStackTrace();
        } catch (ValidationException e) {
            e.printStackTrace();
        } catch (XPathExpressionException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }


    }

    private String readFile( String file ) throws IOException {
        BufferedReader reader = new BufferedReader( new FileReader (file));
        String         line = null;
        StringBuilder  stringBuilder = new StringBuilder();
        String         ls = System.getProperty("line.separator");

        while( ( line = reader.readLine() ) != null ) {
            stringBuilder.append( line );
            stringBuilder.append( ls );
        }

        return stringBuilder.toString();
    }
}
